﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using AuditModel;
using System.Web.Security;
using AuditWeb.Models;
using System.Web.Profile;
using LinqToExcel;
using LinqToExcel.Domain;
using LinqToExcel.Query;
using System.IO;
using System.Reflection;
using System.Drawing;
using DoddleReport.Web;
using DoddleReport;
using System.Globalization;

namespace AuditWeb.Controllers
{ 
    public class ExpertJudgeController : Controller
    {
        private AuditDBEntities db = new AuditDBEntities();
        IAnnualEventBL iaebl = new AnnualEventBL();
        IExpertJudgeBL iejbl = new ExpertJudgeBL();
        string selectedindex = "0";
        //
        // GET: /ExpertJudge/
        [Authorize(Roles = "管理员")]
        public ViewResult Index(string subjectid)
        {
            int _subjectid;
            int.TryParse(subjectid, out _subjectid);
            _subjectid = _subjectid <= 0 ? -1 : _subjectid;
            
            //var expertjudges = db.ExpertJudges.Include("AnnualEvent").Include("Subject");
            AnnualEvent currentevent = iaebl.GetActiveEvents().FirstOrDefault();
            string annualeventid = currentevent.ID;

            IEnumerable<ExpertJudge> expertjudges;
            if(_subjectid==-1)
                expertjudges = from ej in db.ExpertJudges.Include("AnnualEvent").Include("Subject")
                               where ej.AnnualEventID == annualeventid
                               select ej;
            else
                expertjudges = from ej in db.ExpertJudges.Include("AnnualEvent").Include("Subject")
                               where ej.AnnualEventID == annualeventid && ej.SubjectID==_subjectid
                               select ej;

            ViewBag.AnnualEvent = currentevent;
            ViewBag.SelectedIndex = selectedindex;
            ViewBag.AnnualEventId = annualeventid;
            ViewBag.SubjectId = new SelectList(Helpers.GetActiveSubjects(annualeventid), "Id", "Name", _subjectid);
            return View(expertjudges.ToList());
        }

        [Authorize(Roles = "管理员")]
        public ReportResult ExportToExcel(string subjectid)
        {
            //prepare params
            AnnualEvent currentevent = iaebl.GetActiveEvents().FirstOrDefault();
            string annualeventid = currentevent.ID;

            int _subjectid;
            int.TryParse(subjectid, out _subjectid);
            _subjectid = _subjectid <= 0 ? -1 : _subjectid;

            IEnumerable<ExpertJudge> expertjudges;
            if (_subjectid == -1)
                expertjudges = from ej in db.ExpertJudges.Include("AnnualEvent").Include("Subject")
                               where ej.AnnualEventID == annualeventid
                               select ej;
            else
                expertjudges = from ej in db.ExpertJudges.Include("AnnualEvent").Include("Subject")
                               where ej.AnnualEventID == annualeventid && ej.SubjectID == _subjectid
                               select ej;

            List<ExpertJudgeDisplayer> ExpertJudges = new List<ExpertJudgeDisplayer>();

            //rebuild score list for excel
            foreach (var rs in expertjudges)
            {
                ExpertJudgeDisplayer ejd = new ExpertJudgeDisplayer()
                {
                     SerialNumber=rs.SerialNumber,
                      RealName=rs.RealName,
                       SubjectName=rs.Subject.Name,
                        Phone=rs.Phone,
                         ContactAddress=rs.ContactAddress,
                          ZipCode=rs.ZipCode
                };
                ExpertJudges.Add(ejd);
            }

            //generate report
            //to use ToReportSource, you must have the class in Dynamic folder
            var report = new DoddleReport.Report(ExpertJudges.ToReportSource());

            //get property info for headertext
            PropertyInfo[] propertyInfos;
            propertyInfos = typeof(AuditWeb.Models.ExpertJudgeDisplayer).GetProperties();

            //hide all columns and set display name for each column if there is a displayname
            foreach (var field in report.DataFields)
            {
                field.Hidden = true;
                try
                {
                    PropertyInfo pi = (from p in propertyInfos where p.Name == field.Name select p).SingleOrDefault();
                    field.HeaderText = Helpers.getDisplayName(pi);
                    field.Hidden = false;
                }
                catch
                {
                }
            }


            //return report. The report format will decided by the url extension name
            //
            // Try the following sample URLs:
            //
            //  http://localhost:X/doddle/ProductReport.html
            //  http://localhost:X/doddle/ProductReport.txt
            //  http://localhost:X/doddle/ProductReport.xls
            //  http://localhost:X/doddle/ProductReport.xlsx (Requires DoddleReport.OpenXml)
            //  http://localhost:X/doddle/ProductReport.pdf (Requires DoddleReport.iTextSharp or DoddleReport.AbcPdf)
            //  
            return new ReportResult(report);
        }

        //
        // GET: /ExpertJudge/Details/5
        [Authorize(Roles = "管理员")]
        public ViewResult Details(Guid id)
        {
            ExpertJudge expertjudge = db.ExpertJudges.Single(e => e.UserID == id);
            string annualeventid = expertjudge.AnnualEventID;


            ExpertJudgeUpdateModel model = new ExpertJudgeUpdateModel();
            model.ExpertJudge = expertjudge;
            model.AnnualEventID = annualeventid;
            //get email address
            using (aspnetDataContext context = new aspnetDataContext())
            {
                model.Email = context.aspnet_Memberships.SingleOrDefault(mem => mem.UserId == id).Email;
            }

            ViewBag.AnnualEvent = iaebl.GetAnnualEvent(annualeventid);
            ViewBag.SelectedIndex = selectedindex;
            ViewBag.AnnualEventId = annualeventid;
            ViewBag.SubjectID = new SelectList(Helpers.GetActiveSubjects(annualeventid), "Id", "Name", expertjudge.SubjectID);
            return View(model);
        }

        //
        // GET: /ExpertJudge/Create
        [Authorize(Roles = "管理员")]
        public ActionResult Create()
        {
            AnnualEvent currentevent = iaebl.GetActiveEvents().FirstOrDefault();
            string annualeventid = currentevent.ID;

            ViewBag.SubjectID = new SelectList(Helpers.GetActiveSubjects(annualeventid), "Id", "Name");
            ViewBag.AnnualEvent = currentevent;
            ViewBag.SelectedIndex = selectedindex;
            ViewBag.AnnualEventId = annualeventid;
            return View();
        } 

        //
        // POST: /ExpertJudge/Create
        [Authorize(Roles = "管理员")]
        [HttpPost]
        public ActionResult Create(ExpertJudgeModel model)
        {
            string annualeventid = model.AnnualEventID;
            model.ExpertJudge.AnnualEventID = annualeventid;
            if (ModelState.IsValid)
            {
                //Generate new serial number--username
                model.ExpertJudge.SerialNumber = iejbl.GetNewID();
                model.UserName = model.ExpertJudge.SerialNumber;

                // Attempt to register the user
                MembershipCreateStatus createStatus;
                Membership.CreateUser(model.UserName, model.Password, model.Email, null, null, true, null, out createStatus);

                if (createStatus == MembershipCreateStatus.Success)
                {
                    //add role
                    Roles.AddUserToRole(model.UserName, "准评委");
                    using (aspnetDataContext context = new aspnetDataContext())
                    {
                        model.ExpertJudge.UserID = context.aspnet_Users.SingleOrDefault(user => user.UserName == model.UserName).UserId;
                    }
                    iejbl.AddExpertJudge(model.ExpertJudge);
                    //db.ExpertJudges.AddObject(expertjudge);
                    //db.SaveChanges();
                    ProfileBase profile = ProfileBase.Create(model.UserName);
                    profile["ChangePassword"] = true;
                    profile["SubjectId"] = model.ExpertJudge.SubjectID;
                    profile["RealName"] = model.ExpertJudge.RealName;
                    profile["Telephone"] = model.ExpertJudge.Phone;
                    profile.Save();
                    return RedirectToAction("Index", new { id = model.AnnualEventID });  
                }
                else
                {
                    ModelState.AddModelError("",  ErrorCodeToString(createStatus));
                }
                
            }

            ViewBag.AnnualEvent = iaebl.GetAnnualEvent(annualeventid);
            ViewBag.SelectedIndex = selectedindex;
            ViewBag.AnnualEventId = annualeventid;
            ViewBag.SubjectID = new SelectList(Helpers.GetActiveSubjects(annualeventid), "Id", "Name", model.ExpertJudge.SubjectID);
            return View(model);
        }
        
        //
        // GET: /ExpertJudge/Edit/5
 [Authorize(Roles = "管理员")]
        public ActionResult Edit(Guid id)
        {
            ExpertJudge expertjudge = db.ExpertJudges.Single(e => e.UserID == id);
            string annualeventid = expertjudge.AnnualEventID;
           

            ExpertJudgeUpdateModel model = new ExpertJudgeUpdateModel();
            model.ExpertJudge = expertjudge;
            model.AnnualEventID = annualeventid;
            //get email address
            using (aspnetDataContext context = new aspnetDataContext())
            {
                model.Email = context.aspnet_Memberships.SingleOrDefault(mem => mem.UserId == id).Email;
            }
            
            ViewBag.AnnualEvent = iaebl.GetAnnualEvent(annualeventid);
            ViewBag.SelectedIndex = selectedindex;
            ViewBag.AnnualEventId = annualeventid;
            ViewBag.SubjectID = new SelectList(Helpers.GetActiveSubjects(annualeventid), "Id", "Name", expertjudge.SubjectID);
            return View(model);
        }

        //
        // POST: /ExpertJudge/Edit/5
        [Authorize(Roles = "管理员")]
        [HttpPost]
        public ActionResult Edit(ExpertJudgeUpdateModel model)
        {
            string annualeventid = model.ExpertJudge.AnnualEventID;
            if (ModelState.IsValid)
            {
                db.ExpertJudges.Attach(model.ExpertJudge);
                db.ObjectStateManager.ChangeObjectState(model.ExpertJudge, EntityState.Modified);
                db.SaveChanges();
                using (aspnetDataContext context = new aspnetDataContext())
                {
                    var mem = context.aspnet_Memberships.SingleOrDefault(m => m.UserId ==model.ExpertJudge.UserID);
                    mem.Email = model.Email;
                    mem.LoweredEmail = model.Email.ToLower();
                    context.SubmitChanges();
                }
                ProfileBase profile = ProfileBase.Create(model.UserName);
                profile["SubjectId"] = model.ExpertJudge.SubjectID;
                profile["RealName"] = model.ExpertJudge.RealName;
                profile["Telephone"] = model.ExpertJudge.Phone;
                profile.Save();
                return RedirectToAction("Index", new { id = model.ExpertJudge.AnnualEventID });  
            }

            ViewBag.AnnualEvent = iaebl.GetAnnualEvent(annualeventid);
            ViewBag.SelectedIndex = selectedindex;
            ViewBag.AnnualEventId = annualeventid;
            ViewBag.SubjectID = new SelectList(Helpers.GetActiveSubjects(annualeventid), "Id", "Name", model.ExpertJudge.SubjectID);
            return View(model);
        }

        //
        // GET: /ExpertJudge/Delete/5
 [Authorize(Roles = "管理员")]
        public ActionResult Delete(Guid id)
        {
            ExpertJudge expertjudge = db.ExpertJudges.Single(e => e.UserID == id);
            string annualeventid = expertjudge.AnnualEventID;
            
            ViewBag.AnnualEvent = iaebl.GetAnnualEvent(annualeventid);
            ViewBag.SelectedIndex = selectedindex;
            ViewBag.AnnualEventId = annualeventid;
            ViewBag.SubjectID = new SelectList(Helpers.GetActiveSubjects(annualeventid), "Id", "Name", expertjudge.SubjectID);
            return View(expertjudge);
        }

        //
        // POST: /ExpertJudge/Delete/5
        [Authorize(Roles = "管理员")]
        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(Guid id)
        {

            try
            {
                ExpertJudge expertjudge = db.ExpertJudges.Single(e => e.UserID == id);
                string annualeventid = expertjudge.AnnualEventID;
                db.ExpertJudges.DeleteObject(expertjudge);
                db.SaveChanges();
                Membership.DeleteUser(expertjudge.SerialNumber, true);

                return RedirectToAction("Index", new { id = annualeventid });
            }
            catch
            {
                return RedirectToAction("Delete", new { id = id, error=1 });
            }
        }

        //Reset Password
        [Authorize(Roles = "管理员")]
        public ActionResult ResetPassword(Guid id)
        {
            ExpertJudge expertjudge = db.ExpertJudges.Single(e => e.UserID == id);
            string username = "";
            using (aspnetDataContext context = new aspnetDataContext())
            {
                username= context.aspnet_Users.SingleOrDefault(u => u.UserId == id).UserName;
            }
            MembershipUser user = Membership.GetUser(username);            
            ViewBag.NewPassword = user.ResetPassword();
            return View();
        }

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }

        //Import quotas
        [HttpPost]
        [Authorize(Roles = "管理员")]
        public ActionResult Import(HttpPostedFileBase file)
        {
            AnnualEvent currentevent = iaebl.GetActiveEvents().FirstOrDefault();
            string annualeventid = currentevent.ID;
            string importerror = "";

            ViewBag.AnnualEvent = currentevent;
            ViewBag.SelectedIndex = "1";
            ViewBag.AnnualEventId = annualeventid;

            //upload file
            if (file != null && file.ContentLength > 0)
            {
                var fileName = Guid.NewGuid().ToString() + Path.GetExtension(file.FileName);
                var path = Path.Combine(Server.MapPath("~/App_Data/temp"), fileName);
                file.SaveAs(path);
                //get data from file
                var excel = new ExcelQueryFactory(path);
                var ejs = from ej in excel.Worksheet() select ej;
                //add expertjudge
                int count = ejs.Count();
                if (count > 0)
                {
                    int i = 1;
                    foreach (var ej in ejs)
                    {
                        //check and get subject id
                        string subjectname = ej[1].Value.ToString();
                        Subject subject = db.Subjects.SingleOrDefault(s => s.Name == subjectname);
                        if (subject == null)
                        {
                            importerror = string.Format("第{0}条记录学科组名称错误", i.ToString());
                            return RedirectToAction("Index", new { error = importerror });
                        }
                        int subjectid = subject.Id;

                        //check initial password
                        string pwd = ej[4].Value.ToString();
                        if (string.IsNullOrEmpty(pwd)||pwd.Length<6)
                        {
                            importerror = string.Format("第{0}条记录密码不足6位", i.ToString());
                            return RedirectToAction("Index", new { error = importerror });
                        }

                        string realname = ej[2].Value.ToString();
                        string email = ej[3].Value.ToString();
                        string telephone = ej[5].Value.ToString();

                        //create candidatequota object and add to db
                        //Generate new serial number--username
                        string SerialNumber = iejbl.GetNewID();
                        string UserName = SerialNumber;

                        // Attempt to register the user
                        MembershipCreateStatus createStatus;
                        Membership.CreateUser(UserName, pwd, email, null, null, true, null, out createStatus);

                        if (createStatus == MembershipCreateStatus.Success)
                        {
                            //add role
                            Roles.AddUserToRole(UserName, "准评委");
                            Guid userid;
                            using (aspnetDataContext context = new aspnetDataContext())
                            {
                                userid = context.aspnet_Users.SingleOrDefault(user => user.UserName == UserName).UserId;
                            }
                            ExpertJudge judge = new ExpertJudge()
                            {
                                UserID=userid,
                                 AnnualEventID=annualeventid,
                                 Phone=telephone,
                                  SerialNumber=SerialNumber,
                                   RealName=realname,
                                   SubjectID=subjectid
                            };
                            iejbl.AddExpertJudge(judge);
                            //db.ExpertJudges.AddObject(expertjudge);
                            //db.SaveChanges();
                            ProfileBase profile = ProfileBase.Create(UserName);
                            profile["ChangePassword"] = true;
                            profile["RealName"] = realname;
                            profile["Telephone"] = telephone;
                            profile.Save();
                        }
                        else
                        {
                            importerror = string.Format("第{0}条记录创建用户失败", i.ToString());
                            return RedirectToAction("Index", new { error = ErrorCodeToString(createStatus) });
                        }
                        i++;
                    }
                }
                //save change
                try
                {
                    db.SaveChanges();
                }
                catch
                {
                    importerror = "数据重复错误";
                    return RedirectToAction("Index", new { error = importerror });
                }
            }
            else
            {
                importerror = "请选择文件!";
                return RedirectToAction("Index", new { error = importerror });
            }

            return RedirectToAction("Index");

        }

        #region Status Codes
        public static string ErrorCodeToString(MembershipCreateStatus createStatus)
        {
            // See http://go.microsoft.com/fwlink/?LinkID=177550 for
            // a full list of status codes.
            switch (createStatus)
            {
                case MembershipCreateStatus.DuplicateUserName:
                    return "User name already exists. Please enter a different user name.";

                case MembershipCreateStatus.DuplicateEmail:
                    return "A user name for that e-mail address already exists. Please enter a different e-mail address.";

                case MembershipCreateStatus.InvalidPassword:
                    return "The password provided is invalid. Please enter a valid password value.";

                case MembershipCreateStatus.InvalidEmail:
                    return "The e-mail address provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.InvalidAnswer:
                    return "The password retrieval answer provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.InvalidQuestion:
                    return "The password retrieval question provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.InvalidUserName:
                    return "The user name provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.ProviderError:
                    return "The authentication provider returned an error. Please verify your entry and try again. If the problem persists, please contact your system administrator.";

                case MembershipCreateStatus.UserRejected:
                    return "The user creation request has been canceled. Please verify your entry and try again. If the problem persists, please contact your system administrator.";

                default:
                    return "An unknown error occurred. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
            }
        }
        #endregion
    }
}